#!/usr/bin/env node
/**
 * 开发环境助手 MCP 服务器 (离线版)
 * 提供本地环境监控、代码分析和优化建议
 */

import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import {
    CallToolRequestSchema,
    ErrorCode,
    ListToolsRequestSchema,
    McpError,
} from '@modelcontextprotocol/sdk/types.js';
import * as path from 'path';
import logger from './utils/logger';
import {
    executeCommand,
    getSystemInfo,
    checkNetworkConnection,
    detectProjectType,
    findProjectRoot
} from './utils/system';
import { SystemMonitor } from './monitor';

class DevAssistantMcpServer {
    private server: Server;
    private monitor: SystemMonitor | null = null;
    private configPath: string;

    constructor() {
        this.configPath = path.join(__dirname, '..', 'config', 'monitor.json');

        this.server = new Server(
            {
                name: 'dev-assistant-server',
                version: '0.1.0',
            },
            {
                capabilities: {
                    tools: {},
                },
            }
        );

        this.setupToolHandlers();

        // 错误处理
        this.server.onerror = (error) => logger.error('[MCP Error]', { error });
        process.on('SIGINT', async () => {
            await this.cleanup();
            process.exit(0);
        });
    }

    private setupToolHandlers() {
        this.server.setRequestHandler(ListToolsRequestSchema, async () => ({
            tools: [
                {
                    name: 'monitor_system',
                    description: '监控系统资源使用情况，包括CPU、内存、磁盘等',
                    inputSchema: {
                        type: 'object',
                        properties: {},
                        required: [],
                    },
                },
                {
                    name: 'analyze_dependencies',
                    description: '分析项目依赖，检查过时的包、安全漏洞等',
                    inputSchema: {
                        type: 'object',
                        properties: {
                            project_path: {
                                type: 'string',
                                description: '项目路径',
                            },
                            package_manager: {
                                type: 'string',
                                description: '包管理器（npm、pip等）',
                                enum: ['npm', 'pip', 'yarn', 'auto'],
                            },
                        },
                        required: ['project_path'],
                    },
                },
                {
                    name: 'analyze_code',
                    description: '分析代码质量，检查潜在问题',
                    inputSchema: {
                        type: 'object',
                        properties: {
                            file_path: {
                                type: 'string',
                                description: '文件或目录路径',
                            },
                            language: {
                                type: 'string',
                                description: '编程语言',
                                enum: ['javascript', 'python', 'typescript', 'auto'],
                            },
                        },
                        required: ['file_path'],
                    },
                },
                {
                    name: 'optimize_imports',
                    description: '优化代码导入，删除未使用的导入，整理导入顺序',
                    inputSchema: {
                        type: 'object',
                        properties: {
                            file_path: {
                                type: 'string',
                                description: '文件路径',
                            },
                            language: {
                                type: 'string',
                                description: '编程语言',
                                enum: ['javascript', 'python', 'typescript', 'auto'],
                            },
                        },
                        required: ['file_path'],
                    },
                },
                {
                    name: 'check_network',
                    description: '检查网络连接状态',
                    inputSchema: {
                        type: 'object',
                        properties: {
                            target: {
                                type: 'string',
                                description: '目标URL或IP（可选）',
                            },
                        },
                        required: [],
                    },
                },
                {
                    name: 'detect_project',
                    description: '检测项目类型和结构',
                    inputSchema: {
                        type: 'object',
                        properties: {
                            project_path: {
                                type: 'string',
                                description: '项目路径',
                            },
                        },
                        required: ['project_path'],
                    },
                },
                {
                    name: 'start_monitoring',
                    description: '启动系统监控',
                    inputSchema: {
                        type: 'object',
                        properties: {},
                        required: [],
                    },
                },
                {
                    name: 'stop_monitoring',
                    description: '停止系统监控',
                    inputSchema: {
                        type: 'object',
                        properties: {},
                        required: [],
                    },
                },
            ],
        }));

        this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
            const { name, arguments: args } = request.params;

            try {
                switch (name) {
                    case 'monitor_system':
                        return await this.handleMonitorSystem();
                    case 'analyze_dependencies':
                        return await this.handleAnalyzeDependencies(args.project_path, args.package_manager || 'auto');
                    case 'analyze_code':
                        return await this.handleAnalyzeCode(args.file_path, args.language || 'auto');
                    case 'optimize_imports':
                        return await this.handleOptimizeImports(args.file_path, args.language || 'auto');
                    case 'check_network':
                        return await this.handleCheckNetwork(args.target);
                    case 'detect_project':
                        return await this.handleDetectProject(args.project_path);
                    case 'start_monitoring':
                        return await this.handleStartMonitoring();
                    case 'stop_monitoring':
                        return await this.handleStopMonitoring();
                    default:
                        throw new McpError(
                            ErrorCode.MethodNotFound,
                            `未知工具: ${name}`
                        );
                }
            } catch (error) {
                logger.error(`工具执行错误: ${error.message}`, { tool: name, error });

                if (error instanceof McpError) {
                    throw error;
                }

                return {
                    content: [
                        {
                            type: 'text',
                            text: `执行错误: ${error.message}`,
                        },
                    ],
                    isError: true,
                };
            }
        });
    }

    private async handleMonitorSystem() {
        logger.info('执行系统监控');
        const systemInfo = await getSystemInfo();

        return {
            content: [
                {
                    type: 'text',
                    text: JSON.stringify(systemInfo, null, 2),
                },
            ],
        };
    }

    private async handleAnalyzeDependencies(projectPath: string, packageManager: string) {
        logger.info('分析项目依赖', { projectPath, packageManager });

        // 检查项目路径是否存在
        try {
            // 根据项目类型和包管理器执行不同的命令
            let result: string;

            if (packageManager === 'auto') {
                const projectType = await detectProjectType(projectPath);
                packageManager = projectType.packageManager || 'npm';
            }

            switch (packageManager) {
                case 'npm':
                    const outdatedResult = await executeCommand('npm outdated --json', { cwd: projectPath });
                    const auditResult = await executeCommand('npm audit --json', { cwd: projectPath });

                    result = `## NPM 依赖分析\n\n`;
                    result += `### 过时的包\n\n${outdatedResult.stdout || '没有过时的包'}\n\n`;
                    result += `### 安全漏洞\n\n${auditResult.stdout || '没有安全漏洞'}\n\n`;
                    result += `\n运行 \`npm audit fix\` 修复可自动修复的漏洞。`;
                    break;

                case 'yarn':
                    const yarnOutdated = await executeCommand('yarn outdated --json', { cwd: projectPath });
                    result = `## Yarn 依赖分析\n\n${yarnOutdated.stdout || '没有过时的包'}`;
                    break;

                case 'pip':
                    const pipOutdated = await executeCommand('pip list --outdated', { cwd: projectPath });
                    result = `## Python 依赖分析\n\n${pipOutdated.stdout || '没有过时的包'}`;
                    break;

                default:
                    result = `不支持的包管理器: ${packageManager}`;
            }

            return {
                content: [
                    {
                        type: 'text',
                        text: result,
                    },
                ],
            };
        } catch (error) {
            throw new McpError(
                ErrorCode.InternalError,
                `分析依赖失败: ${error.message}`
            );
        }
    }

    private async handleAnalyzeCode(filePath: string, language: string) {
        logger.info('分析代码质量', { filePath, language });

        // 如果语言是自动检测，根据文件扩展名确定语言
        if (language === 'auto') {
            const ext = path.extname(filePath).toLowerCase();
            if (['.js', '.jsx'].includes(ext)) {
                language = 'javascript';
            } else if (['.ts', '.tsx'].includes(ext)) {
                language = 'typescript';
            } else if (['.py'].includes(ext)) {
                language = 'python';
            } else {
                throw new McpError(
                    ErrorCode.InvalidParams,
                    `无法自动检测文件类型: ${filePath}`
                );
            }
        }

        // 根据语言选择不同的代码分析工具
        let result: string;

        switch (language) {
            case 'javascript':
            case 'typescript':
                // 使用 ESLint 分析代码
                const eslintResult = await executeCommand(`npx eslint "${filePath}" --format json`);
                result = `## 代码分析结果 (${language})\n\n`;

                if (eslintResult.success) {
                    result += `ESLint 分析结果:\n\n${eslintResult.stdout || '没有发现问题'}`;
                } else {
                    result += `ESLint 分析失败:\n\n${eslintResult.stderr || '未知错误'}`;
                }
                break;

            case 'python':
                // 使用 pylint 分析代码
                const pylintResult = await executeCommand(`pylint "${filePath}" --output-format=json`);
                result = `## 代码分析结果 (Python)\n\n`;

                if (pylintResult.success) {
                    result += `Pylint 分析结果:\n\n${pylintResult.stdout || '没有发现问题'}`;
                } else {
                    result += `Pylint 分析失败:\n\n${pylintResult.stderr || '未知错误'}`;
                }
                break;

            default:
                throw new McpError(
                    ErrorCode.InvalidParams,
                    `不支持的语言: ${language}`
                );
        }

        return {
            content: [
                {
                    type: 'text',
                    text: result,
                },
            ],
        };
    }

    private async handleOptimizeImports(filePath: string, language: string) {
        logger.info('优化代码导入', { filePath, language });

        // 如果语言是自动检测，根据文件扩展名确定语言
        if (language === 'auto') {
            const ext = path.extname(filePath).toLowerCase();
            if (['.js', '.jsx'].includes(ext)) {
                language = 'javascript';
            } else if (['.ts', '.tsx'].includes(ext)) {
                language = 'typescript';
            } else if (['.py'].includes(ext)) {
                language = 'python';
            } else {
                throw new McpError(
                    ErrorCode.InvalidParams,
                    `无法自动检测文件类型: ${filePath}`
                );
            }
        }

        // 根据语言选择不同的导入优化工具
        let result: string;

        switch (language) {
            case 'javascript':
            case 'typescript':
                // 使用 eslint 自动修复导入问题
                const eslintResult = await executeCommand(`npx eslint "${filePath}" --fix`);
                result = `## 导入优化结果 (${language})\n\n`;

                if (eslintResult.success) {
                    result += `ESLint 优化成功:\n\n${eslintResult.stdout || '文件已优化'}`;
                } else {
                    result += `ESLint 优化失败:\n\n${eslintResult.stderr || '未知错误'}`;
                }
                break;

            case 'python':
                // 使用 isort 优化导入
                const isortResult = await executeCommand(`isort "${filePath}"`);
                result = `## 导入优化结果 (Python)\n\n`;

                if (isortResult.success) {
                    result += `isort 优化成功:\n\n${isortResult.stdout || '文件已优化'}`;
                } else {
                    result += `isort 优化失败:\n\n${isortResult.stderr || '未知错误'}`;
                }
                break;

            default:
                throw new McpError(
                    ErrorCode.InvalidParams,
                    `不支持的语言: ${language}`
                );
        }

        return {
            content: [
                {
                    type: 'text',
                    text: result,
                },
            ],
        };
    }

    private async handleCheckNetwork(target?: string) {
        logger.info('检查网络连接', { target });

        const targets = target
            ? [target]
            : ['github.com', 'google.com', 'npmjs.org', 'pypi.org'];

        const results = [];

        for (const t of targets) {
            const result = await checkNetworkConnection(t);
            results.push({
                target: t,
                success: result.success,
                latency: result.latency,
                error: result.error
            });
        }

        return {
            content: [
                {
                    type: 'text',
                    text: JSON.stringify(results, null, 2),
                },
            ],
        };
    }

    private async handleDetectProject(projectPath: string) {
        logger.info('检测项目类型', { projectPath });

        // 查找项目根目录
        const rootDir = await findProjectRoot(projectPath) || projectPath;

        // 检测项目类型
        const projectType = await detectProjectType(rootDir);

        // 获取项目结构
        const { stdout: fileTree } = await executeCommand(`find "${rootDir}" -type f -not -path "*/node_modules/*" -not -path "*/\\.git/*" -not -path "*/__pycache__/*" | sort | head -n 50`);

        const result = {
            projectPath: rootDir,
            type: projectType.type,
            language: projectType.language,
            packageManager: projectType.packageManager,
            fileStructure: fileTree
        };

        return {
            content: [
                {
                    type: 'text',
                    text: JSON.stringify(result, null, 2),
                },
            ],
        };
    }

    private async handleStartMonitoring() {
        logger.info('启动系统监控');

        if (this.monitor) {
            return {
                content: [
                    {
                        type: 'text',
                        text: '监控系统已经在运行中',
                    },
                ],
            };
        }

        try {
            this.monitor = new SystemMonitor(this.configPath);

            // 设置事件处理
            this.monitor.on('metrics', (metrics) => {
                logger.debug('系统指标', { metrics });
            });

            this.monitor.on('threshold_exceeded', (data) => {
                logger.warn(`指标超过阈值: ${data.metric} (${data.value}%)`, { data });
            });

            this.monitor.on('error', (error) => {
                logger.error('监控错误', { error });
            });

            // 启动监控
            await this.monitor.start();

            return {
                content: [
                    {
                        type: 'text',
                        text: '监控系统已成功启动',
                    },
                ],
            };
        } catch (error) {
            throw new McpError(
                ErrorCode.InternalError,
                `启动监控失败: ${error.message}`
            );
        }
    }

    private async handleStopMonitoring() {
        logger.info('停止系统监控');

        if (!this.monitor) {
            return {
                content: [
                    {
                        type: 'text',
                        text: '监控系统未在运行',
                    },
                ],
            };
        }

        try {
            await this.monitor.stop();
            this.monitor = null;

            return {
                content: [
                    {
                        type: 'text',
                        text: '监控系统已停止',
                    },
                ],
            };
        } catch (error) {
            throw new McpError(
                ErrorCode.InternalError,
                `停止监控失败: ${error.message}`
            );
        }
    }

    private async cleanup() {
        logger.info('清理资源');

        if (this.monitor) {
            await this.monitor.stop();
            this.monitor = null;
        }

        await this.server.close();
    }

    async run() {
        const transport = new StdioServerTransport();
        await this.server.connect(transport);
        logger.info('开发环境助手 MCP 服务器已启动');
    }
}

const server = new DevAssistantMcpServer();
server.run().catch(error => {
    logger.error('服务器启动失败', { error });
    process.exit(1);
});